package router

import (
	"encoding/json"
	"fmt"
	"log"
	"net/http"
	"reflect"
	"time"

	"github.com/tungyao/spruce"
)

func ToJSon(x interface{}, args ...interface{}) ([]byte, error) {
	defer func() {
		r := recover()
		log.Println(r)
	}()
	tt := reflect.TypeOf(x).Elem()
	vv := reflect.ValueOf(x).Elem()
	for i := 0; i < tt.NumField(); i++ {
		switch vv.Field(i).Kind() {
		case reflect.String:
			vv.Field(i).SetString(args[tt.Field(i).Index[0]].(string))
		case reflect.Int:
			vv.Field(i).SetInt(int64(args[tt.Field(i).Index[0]].(int)))
		case reflect.Int64:
			vv.Field(i).SetInt(args[tt.Field(i).Index[0]].(int64))
		case reflect.Bool:
			vv.Field(i).SetBool(args[tt.Field(i).Index[0]].(bool))
		case reflect.Slice:
			vv.Field(i).SetBytes(args[tt.Field(i).Index[0]].([]byte))
		case reflect.Float64:
			vv.Field(i).SetFloat(args[tt.Field(i).Index[0]].(float64))
		case reflect.Float32:
			vv.Field(i).SetFloat(args[tt.Field(i).Index[0]].(float64))
		case reflect.Array:
			// vv.Field(i).
		}
	}
	d, err := json.Marshal(x)
	if err != nil {
		return nil, err
	}
	return d, nil
}

type errJson struct {
	Msg  string
	Yes  string
	Time int64
}
type uuidJSON struct {
	Uuid string
	Time int
}

func ToErrorJson(w http.ResponseWriter, msg interface{}) {
	w.WriteHeader(503)
	w.Header().Set("Content-Type", "application/json")
	e := &ErrorJson{}
	switch msg.(type) {
	case string:
		e.Msg = msg.(string)
	case []byte:
		e.Msg = string(msg.([]byte))
	default:
		d, _ := json.Marshal(msg)
		w.Write(d)
		return
	}
	d, _ := e.MarshalJSON()
	w.Write(d)
}
func ToSuccJson(w http.ResponseWriter, msg interface{}) {
	w.Header().Set("Content-Type", "application/json")
	e := &SuccJson{}
	switch msg.(type) {
	case string:
		e.Msg = msg.(string)
	case []byte:
		e.Msg = string(msg.([]byte))
	}
	d, _ := e.MarshalJSON()
	w.Write(d)
}
func B(str string) []byte {
	return []byte(str)
}

// 基于时间的
func createRandStr(length int) string {
	str := fmt.Sprintf("%x", time.Now().UnixNano())
	strLow := ComplementHex(str[:(len(str)-1)/3], 8)
	strMid := ComplementHex(str[(len(str)-1)/3:(len(str)-1)*2/3], 4)
	<-time.After(1 * time.Nanosecond)
	ti := time.Now().UnixNano()
	return ComplementHex(string(spruce.MD5([]byte(fmt.Sprintf("%s-%x-%s", strLow, ti, strMid)))), length)
}

func createUUID(xtr string) string {
	str := fmt.Sprintf("%x", xtr)
	strLow := ComplementHex(str[:(len(str)-1)/3], 8)
	strMid := ComplementHex(str[(len(str)-1)/3:(len(str)-1)*2/3], 4)
	<-time.After(1 * time.Nanosecond)
	ti := time.Now().UnixNano()
	return fmt.Sprintf("%s-%x-%s-%s", strLow, ti, strMid, createRandStr(8))
}
func createRoomId(xtr string) string {
	str := fmt.Sprintf("%x", xtr)
	strLow := ComplementHex(str[:(len(str)-1)/3], 4)
	strMid := ComplementHex(str[(len(str)-1)/3:(len(str)-1)*2/3], 4)
	<-time.After(1 * time.Nanosecond)
	ti := time.Now().UnixNano()
	return fmt.Sprintf("%s-%x-%s-%s", strLow, ti, strMid, createRandStr(8))
}
func IsError(err error, w http.ResponseWriter) bool {
	if err != nil {
		w.WriteHeader(503)
		w.Header().Set("error", err.Error())
		w.Write([]byte(err.Error()))
		return false
	}
	return true
}
func W(w http.ResponseWriter, body interface{}) {
	w.Header().Set("Content-Type", "application/json")
	switch body.(type) {
	case string:
		w.Write([]byte(body.(string)))
	case []byte:
		w.Write(body.([]byte))
	default:
		d, r := json.Marshal(body)
		if r != nil {
			ToErrorJson(w, r.Error())
		} else {
			w.Write(d)
		}
	}
}
func WsErr(msg interface{}) []byte {
	ret := &ErrorJson{}
	ret.Time = time.Now().Unix()
	ret.Code = ERROR
	switch msg.(type) {
	case string:
		ret.Msg = msg.(string)
	case []byte:
		ret.Msg = string(msg.([]byte))
	case error:
		ret.Msg = msg.(error).Error()
	}
	d, _ := ret.MarshalJSON()
	return d
}
func WsSucc(msg interface{}, data string) []byte {
	ret := &SuccJson{}
	ret.Time = time.Now().Unix()
	ret.Data = data
	switch msg.(type) {
	case string:
		ret.Msg = msg.(string)
	case []byte:
		ret.Msg = string(msg.([]byte))
	case error:
		ret.Msg = msg.(error).Error()
	}
	d, _ := ret.MarshalJSON()
	return d
}
